package io.github.wppli.domain.recommond.rservice;

import cc.jq1024.middleware.redisson.IRedissonService;
import io.github.wppli.domain.recommond.model.entity.ProductEntity;
import io.github.wppli.domain.recommond.repository.IProductRepository;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author li--jiaqiang 2025−03−14
 */
@Slf4j
@AllArgsConstructor
public abstract class AbstractProductRecommendService  {

    protected final IProductRepository productRepository;
    protected final IRedissonService redissonService;

    /**
     * 获取推荐商品
     * @param productId 目标物品ID
     * @param recommendCount 推荐数量
     * @return 推荐商品列表
     * @throws Exception 异常
     */
    public List<ProductEntity> getRecommendEntitiesByItemCF(Long productId, int recommendCount) throws Exception {
        if (productId == null) {
            throw new IllegalArgumentException("productId must not be null");
        }
        if (recommendCount <= 0) {
            throw new IllegalArgumentException("recommendCount must be greater than 0");
        }
        // 从缓存中获取推荐商品
        String key =  "productId_" + productId + "_" + recommendCount;
        List<ProductEntity> recommendByItemFromCache =  redissonService.getList(key, ProductEntity.class);
        if (recommendByItemFromCache != null) {
            log.info("RecommendByItemCF found in cache for productId: {}, recommendCount: {}", productId, recommendCount);
            return recommendByItemFromCache;
        }

        // 从数据库中获取推荐商品
        List<RecommendedItem> recommendedItems = this.recommendProductsByItemCF(productId, recommendCount);
        List<ProductEntity> productEntities = itemsToEntities(recommendedItems, recommendCount);
        // 缓存推荐商品
        redissonService.setValue(key, productEntities, 12, TimeUnit.HOURS);
        return productEntities;
    }

    protected abstract List<RecommendedItem> recommendProductsByItemCF(Long productId, int recommendCount) throws ClassNotFoundException, TasteException;

    /**
     * 获取推荐商品
     * @param productId 目标物品ID
     * @return 推荐商品列表
     * @throws Exception 异常
     */
    public List<ProductEntity> getRecommendEntitiesByItemCF(Long productId) throws Exception {
        return this.getRecommendEntitiesByItemCF(productId, 10);
    }


    /**
     * 获取推荐商品
     * @param userId 用户ID
     * @param topN 推荐数量
     * @param neighborhoodCount 邻居数量
     * @return 推荐商品列表
     */
    public List<ProductEntity> getRecommendEntitiesByUserCF(Long userId, int topN, int neighborhoodCount) throws ClassNotFoundException, TasteException {
        if (userId == null) {
            throw new IllegalArgumentException("userId must not be null");
        }
        if (topN <= 0) {
            throw new IllegalArgumentException("topN must be greater than 0");
        }
        if (neighborhoodCount <= 0) {
            throw new IllegalArgumentException("neighborhoodCount must be greater than 0");
        }

        // 从缓存中获取推荐商品
        String key =  "product_" + userId + "_" + topN + "_" + neighborhoodCount;
        List<ProductEntity> recommendationsFromCache =  redissonService.getList(key, ProductEntity.class);
        if (recommendationsFromCache != null) {
            log.info("getRecommendByUserCFFromCache: {}", recommendationsFromCache);
            return recommendationsFromCache;
        }
        // 缓存未命中，获取推荐商品
        List<RecommendedItem> recommendedItems = this.recommendProductsByUserCF(userId, neighborhoodCount, topN);
        List<ProductEntity> productEntities = itemsToEntities(recommendedItems, topN);
        // 缓存推荐商品
        redissonService.setValue(key, productEntities, 12, TimeUnit.HOURS);
        return productEntities;
    }

    protected abstract List<RecommendedItem> recommendProductsByUserCF(Long userId, int neighborhoodCount, int topN) throws ClassNotFoundException, TasteException;

    /**
     * 获取推荐商品
     * @param userId 用户ID
     * @return 推荐商品列表
     */
    public List<ProductEntity> getRecommendEntitiesByUserCF(Long userId) throws ClassNotFoundException, TasteException {
        return this.getRecommendEntitiesByUserCF(userId, 10, 10);
    }


    /**
     * 获取热门商品
     * @param topN 推荐数量
     * @return 热门商品列表
     */
    public List<ProductEntity> getTopHotProducts(int topN) {
        String key = "top_hot_products_" + topN;
        List<ProductEntity> topHotProducts = redissonService.getList(key, ProductEntity.class);
        if (topHotProducts != null) {
            return topHotProducts;
        }
        topHotProducts = productRepository.getTopHotProducts(topN);
        redissonService.setValue(key, topHotProducts, 10, TimeUnit.MINUTES);
        return topHotProducts;
    }
    public List<ProductEntity> getTopHotProducts() {
        return this.getTopHotProducts(10);
    }


    private List<ProductEntity> itemsToEntities(List<RecommendedItem> recommendedItems, int topN)  {
        if (recommendedItems.isEmpty()) {
            return getTopHotProducts(topN);
        }
        // 按照评分排序并取前 topN 个商品
        List<Long> productIds = new LinkedList<>();
        recommendedItems.stream().map(RecommendedItem::getItemID).forEach(productIds::add);
        return   productRepository.queryByIds(productIds);
    }

}